package com.fangmou.ing.publish.freemarker;

import com.fangmou.ing.publish.freemarker.directive.*;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModelException;

import java.util.Map;
import java.util.Random;

/**
 * @author kongdy
 */
public class DirectiveUtils {

    public static final String BLOCK = "__<@ftl_override>__";
    public static final String SUPER = "__<@ftl_super>__";
    public static final String OVERRIDE_CURRENT_NODE = "__<@ftl_override_current_node>__";

    /**
     * 自定义命令
     */
    public static final String DIRECTIVE_BLOCK = "_block";
    public static final String DIRECTIVE_OVERRIDE = "_override";
    public static final String DIRECTIVE_EXTENDS = "_extends";
    public static final String DIRECTIVE_DELETE = "_delete";
    public static final String DIRECTIVE_SUPER = "_super";
    public static final String DIRECTIVE_INSERT = "_insert";
    public static final String DIRECTIVE_MOVE = "_move";


    public static final String LOCATE_BEFORE = "before";
    public static final String LOCATE_AFTER = "after";

    public static String getOverrideVariableName(String name) {
        return BLOCK + name;
    }

    /**
     * 获取引用父级block占位符
     *
     * @param name
     * @return
     */
    public static String getSuperPlaceholder(String name) {
        return SUPER + name;
    }

    /**
     * 注册自定义命令
     *
     * @param conf
     */
    public static void exposeRapidMacros(Configuration conf) {
        conf.setSharedVariable(DIRECTIVE_BLOCK, new BlockDirective());
        conf.setSharedVariable(DIRECTIVE_EXTENDS, new ExtendsDirective());
        conf.setSharedVariable(DIRECTIVE_OVERRIDE, new OverrideDirective());
        conf.setSharedVariable(DIRECTIVE_SUPER, new SuperDirective());
        conf.setSharedVariable(DIRECTIVE_DELETE, new DeleteDirective());
        conf.setSharedVariable(DIRECTIVE_INSERT, new InsertDirective());
        conf.setSharedVariable(DIRECTIVE_MOVE, new MoveDirective());
    }


    /**
     * 取必传参数
     *
     * @param params
     * @param key
     * @return
     * @throws TemplateException
     */
    public static String getRequiredParam(Map params, String key) throws TemplateException {
        Object value = params.get(key);
        if (value == null || "".equals(value.toString())) {
            throw new TemplateModelException("not found required parameter:" + key + " for directive");
        }
        return value.toString();
    }

    /**
     * 取可选参数，空则返回默认值
     *
     * @param params
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getParam(Map params, String key, String defaultValue) {
        Object value = params.get(key);
        return value == null ? defaultValue : value.toString();
    }

    /**
     * 获取位置参数，默认或传值无效时取“before”
     *
     * @param params
     * @return
     */
    public static String getLocateParam(Map params) {
        Object obj = params.get("locate");
        if (obj != null && DirectiveUtils.LOCATE_AFTER.equals(obj.toString())) {
            return DirectiveUtils.LOCATE_AFTER;
        }
        return DirectiveUtils.LOCATE_BEFORE;
    }

    public static DirectiveBodyWraper getOverrideBody(Environment env, String name) throws TemplateModelException {
        DirectiveBodyWraper value = (DirectiveBodyWraper) env.getVariable(getOverrideVariableName(name));
        return value;
    }

    public static void setTopBodyForParentBody(Environment env,
                                               DirectiveBodyWraper topBody,
                                               DirectiveBodyWraper overrideBody) {
        DirectiveBodyWraper parent = overrideBody;
        while (parent.parentBody != null) {
            parent = parent.parentBody;
        }
        parent.parentBody = topBody;
    }

}
